-- Copyright © 2012 Xianghar  <xian@zron.de>
-- All Rights Reserved.

if select(2,UnitClass("player")) ~= "MONK" then return end

local _, MonkTimers = ...

local SpellIDs = MonkTimers.SpellIDs
local SpellTextures = MonkTimers.SpellTextures
local SpellNames = MonkTimers.SpellNames
local AvailableSpells = MonkTimers.AvailableSpells
local TigerPalmBuff = SpellNames[SpellIDs.PowerGuard]

local stagger = CreateFrame("StatusBar", "MonkTimers_StaggerBar", UIParent, "XiTimersTimerBarTemplate, SecureActionButtonTemplate, SecureHandlerBaseTemplate")
local staggerButton = CreateFrame("Button", "MonkTimers_StaggerBarButton", MonkTimers_StaggerBar, "ActionButtonTemplate, SecureActionButtonTemplate")
RegisterStateDriver(stagger, "petbattle", "[petbattle][overridebar][possessbar] active; none")
RegisterStateDriver(stagger, "combat", "[combat] active; none")
stagger:WrapScript(stagger, "OnAttributeChanged", [[
	if not self:GetAttribute("active") then return end
	if name == "state-petbattle" then
		if value == "active" then
			self:Hide()
		elseif not self:GetAttribute("HideOOC") then
			self:Show()
		end
	elseif name == "state-combat" then
		if value == "active" then
			self:Show()
		elseif self:GetAttribute("HideOOC") then
			self:Hide()
		end
	end
]])

local cds = {}
--local spells = {SpellNames[SpellIDs.StormStrike], SpellNames[SpellIDs.EarthShock], SpellNames[SpellIDs.LavaLash], SpellNames[SpellIDs.FlameShock]}
local playerName = UnitName("player")
local role = 1

MonkTimers.num_CD_Spells = num_CD_Spells

local function NoUpdate()
end


local CD_Spells = {
    [1] = {
        SpellIDs.TigerPalm, -- 1
        SpellIDs.BlackoutKick,
        SpellIDs.ElusiveBrew,
        SpellIDs.KegSmash, 
        SpellIDs.ExpelHarm,  -- 5
        SpellIDs.Guard,
        SpellIDs.Provoke,
        SpellIDs.GrappleWeapon,  -- 8
		SpellIDs.SpearHandStrike,
		SpellIDs.Clash,
    },
    [2] = {
        SpellIDs.TigerPalm, 
		SpellIDs.BlackoutKick,
		SpellIDs.RenewingMist,
		SpellIDs.ChiWave,
		SpellIDs.Detox,
		SpellIDs.ThunderFocusTea,		
		SpellIDs.ExpelHarm,		
		SpellIDs.GrappleWeapon,
    },
    [3] = {
        SpellIDs.TigerPalm,  -- 1
		SpellIDs.BlackoutKick,
		SpellIDs.RisingSunKick,
		SpellIDs.TigereyeBrew,
		SpellIDs.FistsOfFury,
		SpellIDs.EnergizingBrew,  -- 5		
		SpellIDs.FlyingSerpentKick,		
		SpellIDs.SpearHandStrike,
		SpellIDs.ExpelHarm,		
		SpellIDs.GrappleWeapon,
    },
}

local num_CD_Spells = {[1]=#CD_Spells[1],[2]=#CD_Spells[2],[3]=#CD_Spells[3],}

MonkTimers.CD_Spells = CD_Spells

local ElusiveBrewEvent
local TigerPalmEvent
local BlackoutKickEvent
local BlackoutKickWWEvent
local GuardEvent
local CDAndBuffEvent
local DampenHarmEvent
local TigereyeBrewEvent
local SerpentsZealEvent
local ChiBarEvent
local ChiBarUpdate
local StaggerEvent

local function ActivateCD(self)
    XiTimers.Activate(self)
end

   
local function ChangeTimerOrder(self,spell)
    if InCombatLockdown() then return end
    if not spell then return end
    local _,spell1 = GetSpellBookItemInfo(spell, "BOOKTYPE_SPELL")
    local spell2 = self:GetAttribute("orderspell")    
    if not spell2 or not spell1 then return end
    local spellnum1, spellnum2 = nil,nil
    for i=1,num_CD_Spells[role] do
        if CD_Spells[role][i] == spell1 then spellnum1 = i end
        if CD_Spells[role][i] == spell2 then spellnum2 = i end        
    end
    if not spellnum1 or not spellnum2 then return end
    local order1, order2 = nil
    for i=1,#MonkTimers.ActiveProfile.Timer_Order[role] do
        if MonkTimers.ActiveProfile.Timer_Order[role][i] == spellnum1 then order1 = i end
        if MonkTimers.ActiveProfile.Timer_Order[role][i] == spellnum2 then order2 = i end
    end
    if not order1 or not order2 then return end
    MonkTimers.ActiveProfile.Timer_Order[role][order1], MonkTimers.ActiveProfile.Timer_Order[role][order2] =
        MonkTimers.ActiveProfile.Timer_Order[role][order2], MonkTimers.ActiveProfile.Timer_Order[role][order1]
    MonkTimers.LayoutTimers()
end
   
function MonkTimers.CreateTimers()
    for i = 1,11 do
        cds[i] = XiTimers:new()
        cds[i].events[1] = "SPELL_UPDATE_COOLDOWN"
        cds[i].dontFlash = true
        cds[i].timeStyle = "sec"
        cds[i].button.anchorframe = MonkTimersFrame
        cds[i].button:SetAttribute("*type*", "spell")
        --cds[i].activate = ActivateCD
        cds[i].reverseAlpha = true
        --cds[i].dontAlpha = true
        cds[i].button.icon:SetAlpha(1)
        cds[i].button:SetScript("OnEvent", MonkTimers.TimerEvents)
        cds[i].button:RegisterForClicks("LeftButtonUp", "RightButtonUp", "MiddleButtonUp")
		
		cds[i].button:SetScript("OnEnter", function(self) MonkTimers.Tooltip(self) end)
		cds[i].button:SetScript("OnLeave", function(self) MonkTimers.HideTooltip(self) end)
    end
	MonkTimers.Timers = cds


    for i=1,11 do
        cds[i].button:SetAttribute("_ondragstart",[[if IsShiftKeyDown() and self:GetAttribute("orderspell")~=0 then
                                                    return "spell", self:GetAttribute("orderspell")
                                              else control:CallMethod("StartMove") end]])
        cds[i].button:SetAttribute("_onreceivedrag",[[ if kind == "spell" then
                                                   control:CallMethod("ChangeTimerOrder", value, ...)
                                                    return "clear"
                                              end]])
        cds[i].button.ChangeTimerOrder = ChangeTimerOrder
    end
	
	stagger.icon = getglobal("MonkTimers_StaggerBarIcon")
    stagger.background = getglobal("MonkTimers_StaggerBarBackground")
    stagger.icon:SetTexture(SpellTextures[SpellIDs.StaggerLight])
    stagger.icon:Show()
    stagger.icon:SetPoint("RIGHT", stagger, "LEFT")
    stagger.background:Show()
    stagger.background:SetValue(1)
    stagger.background:SetWidth(120)
    stagger.background:SetStatusBarColor(0, 1, 0, 0.3)
    stagger:SetWidth(120)
    stagger:SetScript("OnEvent", StaggerEvent)	
    stagger.text = getglobal("MonkTimers_StaggerBarTime")
	stagger.text:ClearAllPoints()
	stagger.text:SetPoint("CENTER", stagger, "CENTER")
	MonkTimers.stagger = stagger
    MonkTimers.staggerButton = staggerButton
    --staggerButton:SetWidth(100)
	--staggerButton:Hide()
    --staggerButton:SetHeight(stagger.background:GetHeight())
	staggerButton:ClearAllPoints()
	staggerButton:SetAllPoints(stagger)
    staggerButton:SetPoint("CENTER", stagger, "CENTER")
    staggerButton:SetNormalTexture(nil)
    staggerButton:SetHighlightTexture("Interface\\AddOns\\TotemTimers\\MaelstromHilight")
    staggerButton:SetPushedTexture("Interface\\AddOns\\TotemTimers\\MaelstromPushed")
    staggerButton:SetAttribute("*type*", "spell")
    staggerButton:RegisterForClicks("LeftButtonUp", "RightButtonUp")
    staggerButton:SetAttribute("*spell1", SpellNames[SpellIDs.PurifyingBrew])
	
	MonkTimers.harmonyBar = MonkTimersHarmonyBar
	
	MonkTimersHarmonyBar:SetScale(0.9)
	MonkTimersHarmonyBarEnergyBar:SetFrameLevel(MonkTimersHarmonyBarEnergyBar:GetFrameLevel()-1)
	MonkTimersHarmonyBar:SetScript("OnEvent", ChiBarEvent)
	MonkTimersHarmonyBar.energyBar = MonkTimersHarmonyBarEnergyBar
	MonkTimersHarmonyBar.maxLight = 4
	MonkTimersHarmonyBar:SetScript("OnUpdate", ChiBarUpdate)
	
	MonkTimersHarmonyBar:RegisterForDrag("LeftButton")
	MonkTimersHarmonyBar:SetScript("OnDragStart", function(self) MonkTimersFrame:StartMoving()  end)
	MonkTimersHarmonyBar:SetScript("OnDragStop", function(self) MonkTimersFrame:StopMovingOrSizing() if XiTimers.SaveFramePositions then XiTimers.SaveFramePositions() end end)
	MonkTimersHarmonyBarEnergyBar:RegisterForDrag("LeftButton")
	MonkTimersHarmonyBarEnergyBar:SetScript("OnDragStart", function(self) MonkTimersFrame:StartMoving()  end)
	MonkTimersHarmonyBarEnergyBar:SetScript("OnDragStop", function(self) MonkTimersFrame:StopMovingOrSizing() if XiTimers.SaveFramePositions then XiTimers.SaveFramePositions() end end)
	MonkTimersHarmonyBar:EnableMouse(true)
	MonkTimersHarmonyBarEnergyBar:EnableMouse(true)
end


function MonkTimers.ConfigTimers()
	if InCombatLockdown() then
		MonkTimers.updateAfterCombat = true
		return
	end
    role = GetSpecialization()
    if not role then role = 3 end
    
    for i=1,11 do
        cds[i]:Deactivate()
    end
	
	stagger:UnregisterEvent("UNIT_AURA")
    stagger:UnregisterEvent("PLAYER_REGEN_ENABLED")
    stagger:UnregisterEvent("PLAYER_REGEN_DISABLED")
    stagger:Hide()
	MonkTimersHarmonyBar:UnregisterAllEvents()
	MonkTimersHarmonyBar:Hide()
    
    if not MonkTimers.ActiveProfile.Timers then return end

    for i=1,num_CD_Spells[role] do
        cds[i].button.cdspell = CD_Spells[role][i]
        cds[i].button.cdspellName = SpellNames[CD_Spells[role][i]]
        cds[i].button.icon:SetTexture(SpellTextures[CD_Spells[role][i]])
        cds[i].button:SetAttribute("*spell1", CD_Spells[role][i])
        cds[i].rangeCheck = SpellNames[CD_Spells[role][i]]
        cds[i].manaCheck = SpellNames[CD_Spells[role][i]]
        cds[i].button:SetScript("OnEvent", MonkTimers.TimerEvents)
        cds[i].Update = nil
        cds[i].prohibitCooldown = false
        cds[i].button:SetAttribute("orderspell", CD_Spells[role][i])
        cds[i].events = {"SPELL_UPDATE_COOLDOWN"}
        cds[i].barTimerOnly = false
        cds[i].reverseAlpha = true
        cds[i].button.bar:SetStatusBarColor(0.6,0.6,1,0.7)
		stagger.active = false
		stagger:SetAttribute("active", false)
    end
    
    
    if role == 1 then
		cds[1].prohibitCooldown = true
		cds[1].button:SetScript("OnEvent", TigerPalmEvent)
		cds[1].events[1] = "UNIT_AURA"
		cds[1].barTimerOnly = true
    
		cds[2].events[1] = "UNIT_AURA"
		cds[2].button:SetScript("OnEvent", BlackoutKickEvent)
        TigerPalmBuff = SpellNames[SpellIDs.PowerGuard]
        cds[3].events[1] = "UNIT_AURA"
        cds[3].button:SetScript("OnEvent", ElusiveBrewEvent)
        cds[3].reverseAlpha = false
        cds[6].events[1] = "UNIT_AURA"
        cds[6].button:SetScript("OnEvent", GuardEvent)
		cds[6].events[2] = "SPELL_ACTIVATION_OVERLAY_GLOW_SHOW"
		cds[6].events[3] = "SPELL_ACTIVATION_OVERLAY_GLOW_HIDE" 
		cds[6].button.glowSpell = SpellIDs.Guard
		
        cds[8].events[2] = "UNIT_AURA"		
        cds[8].button:SetScript("OnEvent", CDAndBuffEvent)
        cds[10].button:SetScript("OnEvent", CDAndBuffEvent)
        cds[10].events[2] = "UNIT_AURA"
        cds[11].events[2] = "UNIT_AURA"
        cds[11].button:SetScript("OnEvent", CDAndBuffEvent)
        cds[9].events[2] = "UNIT_AURA"
        cds[9].button:SetScript("OnEvent", DampenHarmEvent)
		
		if MonkTimers.ActiveProfile.StaggerBar and AvailableSpells[SpellIDs.OxStance] then
			stagger:RegisterUnitEvent("UNIT_AURA", "player")
			stagger:RegisterEvent("PLAYER_REGEN_ENABLED")
			stagger:RegisterEvent("PLAYER_REGEN_DISABLED")
			stagger:Show()
			if not InCombatLockdown() and MonkTimers.ActiveProfile.HideTimersOOC then 
				stagger:Hide()
			end
			stagger:SetMinMaxValues(0, MonkTimers.ActiveProfile.StaggerMax or 100)
			stagger.background:SetMinMaxValues(0, MonkTimers.ActiveProfile.StaggerMax or 100)
			stagger.background:SetValue(MonkTimers.ActiveProfile.StaggerMax or 100)
			stagger.background:Show()
			stagger.background:SetStatusBarColor(0,1,0,0.3)
			stagger.active = true
			stagger:SetAttribute("active", true)
		end
    elseif role == 3 then
        TigerPalmBuff = SpellNames[SpellIDs.TigerPower]
		cds[1].prohibitCooldown = true
		cds[1].button:SetScript("OnEvent", TigerPalmEvent)
		cds[1].events[1] = "UNIT_AURA"
		cds[1].barTimerOnly = true	
		cds[1].events[2] = "SPELL_ACTIVATION_OVERLAY_GLOW_SHOW"
		cds[1].events[3] = "SPELL_ACTIVATION_OVERLAY_GLOW_HIDE"
		cds[1].button.glowSpell = SpellIDs.TigerPalm
		
		cds[2].prohibitCooldown = true
		cds[2].events[1] = "UNIT_AURA"
		cds[2].button:SetScript("OnEvent", BlackoutKickWWEvent)
		cds[2].events[2] = "SPELL_ACTIVATION_OVERLAY_GLOW_SHOW"
		cds[2].events[3] = "SPELL_ACTIVATION_OVERLAY_GLOW_HIDE"
		cds[2].button.glowSpell = SpellIDs.BlackoutKick		
		
        cds[4].events[1] = "UNIT_AURA"
        cds[4].button:SetScript("OnEvent", TigereyeBrewEvent)
        cds[4].reverseAlpha = false
		stagger.active = false
	else
		TigerPalmBuff = SpellNames[SpellIDs.VitalMists]
		cds[1].prohibitCooldown = true
		cds[1].barTimerOnly = true
		cds[1].button:SetScript("OnEvent", TigerPalmEvent)
		cds[1].events[1] = "UNIT_AURA"
	
		cds[3].prohibitCooldown = true
		cds[3].barTimerOnly = true
		cds[3].events[1] = "UNIT_AURA"
		cds[3].button:SetScript("OnEvent", SerpentsZealEvent)
		
    end

    for i=1,num_CD_Spells[role] do 
        if MonkTimers.ActiveProfile.Timer_Spells[role][i] == nil then MonkTimers.ActiveProfile.Timer_Spells[role][i] = true end
        if MonkTimers.ActiveProfile.Timer_Order[role][i] == nil then MonkTimers.ActiveProfile.Timer_Order[role][i] = i end
        if MonkTimers.ActiveProfile.Timer_Spells[role][i] and AvailableSpells[CD_Spells[role][MonkTimers.ActiveProfile.Timer_Order[role][i]]] then
            cds[i]:Activate()
        end
    end
	
	if MonkTimers.ActiveProfile.ChiBar then
		if not InCombatLockdown() and MonkTimers.ActiveProfile.HideTimersOOC then 
			MonkTimersHarmonyBar:Hide()
		else
			MonkTimersHarmonyBar:Show()
		end
		MonkTimersHarmonyBar.active = true
		MonkTimersHarmonyBar:RegisterUnitEvent("UNIT_POWER", "player")
		MonkTimersHarmonyBar:RegisterUnitEvent("UNIT_MAXPOWER", "player")
		MonkTimersHarmonyBar:RegisterEvent("PLAYER_REGEN_ENABLED")
		MonkTimersHarmonyBar:RegisterEvent("PLAYER_REGEN_DISABLED")
		MonkTimersHarmonyBar:RegisterEvent("PET_BATTLE_OPENING_START")
		MonkTimersHarmonyBar:RegisterEvent("PET_BATTLE_CLOSE")
		--MonkTimersHarmonyBar:RegisterEvent("UNIT_ENTERED_VEHICLE")
		--MonkTimersHarmonyBar:RegisterEvent("UNIT_EXITED_VEHICLE")
		--MonkTimersHarmonyBar:RegisterUnitEvent("UNIT_POWER_FREQUENT", "player")
		if role == 1 or role == 3 then
			MonkTimersHarmonyBarEnergyBar:SetStatusBarColor(0.8,0.8,0,0.8)
			local maxpower = UnitPowerMax("player", SPELL_POWER_ENERGY)
			MonkTimersHarmonyBarEnergyBar:SetMinMaxValues(0,maxpower)
			MonkTimersHarmonyBar.powerType = SPELL_POWER_ENERGY			
		else
			MonkTimersHarmonyBarEnergyBar:SetStatusBarColor(0,0,1,0.8)
			local maxpower = UnitPowerMax("player", SPELL_POWER_MANA)
			MonkTimersHarmonyBarEnergyBar:SetMinMaxValues(0,maxpower)
			MonkTimersHarmonyBar.powerType = SPELL_POWER_MANA
		end
	else
		MonkTimersHarmonyBar.active = false
	end	
end

local active_cds = {}

local function ConvertCoords(frame1, frame2)
    return frame1:GetEffectiveScale()/frame2:GetEffectiveScale()
end


function MonkTimers.LayoutTimers()
	if InCombatLockdown() then
		MonkTimers.updateAfterCombat = true
		return
	end
    wipe(active_cds)
    for i=1,num_CD_Spells[role] do
        if cds[MonkTimers.ActiveProfile.Timer_Order[role][i]].active then
            table.insert(active_cds,cds[MonkTimers.ActiveProfile.Timer_Order[role][i]])
        end
    end
    for i=1,11 do 
        cds[i]:ClearAnchors()
        cds[i].button:ClearAllPoints()
    end
	stagger:ClearAllPoints()
	MonkTimersHarmonyBar:ClearAllPoints()

	local point, relframe, relpoint
    if #active_cds == 0 then
		point = "TOP"
		relframe = MonkTimersFrame
		relpoint = "BOTTOM"
		inactivepoint = "BOTTOM"
    elseif #active_cds == 1 then
        active_cds[1].button:SetPoint("CENTER", MonkTimersFrame)
		point = "TOP"
		relframe = active_cds[1].button
		relpoint = "BOTTOM"
		inactivepoint = "BOTTOM"
    elseif #active_cds == 2 then
        active_cds[1].button:SetPoint("RIGHT", MonkTimersFrame, "CENTER", -3, 0)
        active_cds[2]:Anchor(active_cds[1], "LEFT")
		point = "TOP"
		relframe = active_cds[2].button
		relpoint = "BOTTOMLEFT"
		inactivepoint = "BOTTOM"
    elseif #active_cds == 3 then
        active_cds[2].button:SetPoint("CENTER", MonkTimersFrame)
        active_cds[1]:Anchor(active_cds[2], "RIGHT")
        active_cds[3]:Anchor(active_cds[2], "LEFT")
		point = "TOPLEFT"
		relframe = active_cds[1].button
		relpoint = "BOTTOMLEFT"
		inactivepoint = "BOTTOMLEFT"
    elseif #active_cds == 4 then
        active_cds[2].button:SetPoint("RIGHT", MonkTimersFrame, "LEFT", -3, 0)
        active_cds[1]:Anchor(active_cds[2], "RIGHT")
        active_cds[3]:Anchor(active_cds[2], "LEFT")
        active_cds[4]:Anchor(active_cds[3], "LEFT")
		point = "TOPLEFT"
		relframe = active_cds[1].button
		relpoint = "BOTTOM"
		inactivepoint = "BOTTOMLEFT"
    elseif #active_cds == 5 then
        active_cds[1].button:SetPoint("RIGHT", MonkTimersFrame, "CENTER", -3, 0)
        active_cds[2]:Anchor(active_cds[1], "LEFT")
        active_cds[3]:Anchor(active_cds[1], "TOPRIGHT", "BOTTOM", true)
        active_cds[4]:Anchor(active_cds[3], "LEFT")
        active_cds[5]:Anchor(active_cds[4], "LEFT")
		point = "TOPLEFT"
		relframe = active_cds[3].button
		relpoint = "BOTTOMLEFT"
		inactivepoint = "BOTTOMLEFT"
    elseif #active_cds == 6 then
        active_cds[2].button:SetPoint("CENTER", MonkTimersFrame)
        active_cds[1]:Anchor(active_cds[2], "RIGHT")
        active_cds[3]:Anchor(active_cds[2], "LEFT")
        active_cds[5]:Anchor(active_cds[2], "TOP", "BOTTOM")
        active_cds[4]:Anchor(active_cds[5],"RIGHT")
        active_cds[6]:Anchor(active_cds[5],"LEFT")
		point = "TOPLEFT"
		relframe = active_cds[4].button
		relpoint = "BOTTOMLEFT"
		inactivepoint = "BOTTOMLEFT"
    elseif #active_cds == 7 then
        active_cds[2].button:SetPoint("CENTER", MonkTimersFrame)
        active_cds[1]:Anchor(active_cds[2], "RIGHT")
        active_cds[3]:Anchor(active_cds[2], "LEFT")
        active_cds[5]:Anchor(active_cds[2], "TOPRIGHT", "BOTTOM", true)
        active_cds[4]:Anchor(active_cds[5], "RIGHT")
        active_cds[6]:Anchor(active_cds[5], "LEFT")
        active_cds[7]:Anchor(active_cds[6], "LEFT")
		point = "TOPLEFT"
		relframe = active_cds[4].button
		relpoint = "BOTTOM"
		inactivepoint = "BOTTOMLEFT"
    elseif #active_cds == 8 then
        active_cds[2].button:SetPoint("RIGHT", MonkTimersFrame, -3, 0)
        active_cds[1]:Anchor(active_cds[2], "RIGHT")
        active_cds[3]:Anchor(active_cds[2], "LEFT")
        active_cds[4]:Anchor(active_cds[3], "LEFT")
        active_cds[5]:Anchor(active_cds[1], "TOP", "BOTTOM")
        active_cds[6]:Anchor(active_cds[2], "TOP", "BOTTOM")
        active_cds[7]:Anchor(active_cds[3], "TOP", "BOTTOM")
        active_cds[8]:Anchor(active_cds[4], "TOP", "BOTTOM")
		point = "TOPLEFT"
		relframe = active_cds[5].button
		relpoint = "BOTTOM"
		inactivepoint = "BOTTOMLEFT"
    elseif #active_cds == 9 then
        active_cds[2].button:SetPoint("RIGHT", MonkTimersFrame, -3, 0)
        active_cds[1]:Anchor(active_cds[2], "RIGHT")
        active_cds[3]:Anchor(active_cds[2], "LEFT")
        active_cds[4]:Anchor(active_cds[3], "LEFT")
        active_cds[6]:Anchor(active_cds[2], "TOPRIGHT", "BOTTOM", true)
        active_cds[5]:Anchor(active_cds[6], "RIGHT")
        active_cds[7]:Anchor(active_cds[6], "LEFT")
        active_cds[8]:Anchor(active_cds[7], "LEFT")
        active_cds[9]:Anchor(active_cds[8], "LEFT")
		point = "TOPLEFT"
		relframe = active_cds[6].button
		relpoint = "BOTTOMLEFT"
		inactivepoint = "BOTTOMLEFT"
    elseif #active_cds == 10 then
        active_cds[3].button:SetPoint("CENTER", MonkTimersFrame)
        active_cds[2]:Anchor(active_cds[3], "RIGHT")
        active_cds[1]:Anchor(active_cds[2], "RIGHT")
        active_cds[4]:Anchor(active_cds[3], "LEFT")
        active_cds[5]:Anchor(active_cds[4], "LEFT")
        active_cds[6]:Anchor(active_cds[1], "TOP", "BOTTOM")
        active_cds[7]:Anchor(active_cds[2], "TOP", "BOTTOM")
        active_cds[8]:Anchor(active_cds[3], "TOP", "BOTTOM")
        active_cds[9]:Anchor(active_cds[4], "TOP", "BOTTOM")
        active_cds[10]:Anchor(active_cds[5], "TOP", "BOTTOM")
		point = "TOPLEFT"
		relframe = active_cds[7].button
		relpoint = "BOTTOMLEFT"
		inactivepoint = "BOTTOMLEFT"
    elseif #active_cds == 11 then
        active_cds[3].button:SetPoint("CENTER", MonkTimersFrame)
        active_cds[2]:Anchor(active_cds[3], "RIGHT")
        active_cds[1]:Anchor(active_cds[2], "RIGHT")
        active_cds[4]:Anchor(active_cds[3], "LEFT")
        active_cds[5]:Anchor(active_cds[4], "LEFT")
        active_cds[6]:Anchor(active_cds[1], "TOPRIGHT", "BOTTOM", true)
        active_cds[7]:Anchor(active_cds[6], "LEFT")
        active_cds[8]:Anchor(active_cds[7], "LEFT")
        active_cds[9]:Anchor(active_cds[8], "LEFT")
        active_cds[10]:Anchor(active_cds[9], "LEFT")
        active_cds[11]:Anchor(active_cds[10], "LEFT")
		point = "TOPLEFT"
		relframe = active_cds[7].button
		relpoint = "BOTTOM"
		inactivepoint = "BOTTOMLEFT"
    end
    local vertdist = not (MonkTimers.ActiveProfile.StaggerOnTop or MonkTimers.ActiveProfile.TimersOnButtons) and MonkTimers.ActiveProfile.TimeHeight or 0
	vertdist = vertdist + 5
    
	if stagger.active then
		if not MonkTimers.ActiveProfile.StaggerOnTop then 
			stagger:SetPoint(point, relframe, relpoint, 0, -vertdist)
		else
			--stagger:SetPoint("BOTTOMRIGHT", MonkTimersFrame, "CENTER", -(MonkTimers.ActiveProfile.TimerSize*3.5+5), vertdist)		
		end
	else
		stagger:SetPoint(inactivepoint, relframe, relpoint)
	end
	MonkTimersHarmonyBar:SetPoint("TOP", MonkTimers.stagger, "BOTTOM", 0, 17)
end

function MonkTimers.ActivateTimers()
    MonkTimers.ConfigTimers()
    MonkTimers.LayoutTimers()
end

function MonkTimers.DeactivateTimers()
    for k,v in pairs(cds) do
        v:Deactivate()
    end
	stagger:UnregisterEvent("UNIT_AURA")
    stagger:UnregisterEvent("PLAYER_REGEN_ENABLED")
    stagger:UnregisterEvent("PLAYER_REGEN_DISABLED")
    stagger:Hide()
	MonkTimersHarmonyBar:UnregisterAllEvents()
	MonkTimersHarmonyBar:Hide()
end

local function GlowEvent(self, event, spell)
    if event == "SPELL_ACTIVATION_OVERLAY_GLOW_SHOW" then 
		if spell == self.glowSpell then
			ActionButton_ShowOverlayGlow(self)			
		end
	elseif event == "SPELL_ACTIVATION_OVERLAY_GLOW_HIDE" then		
		if spell == self.glowSpell then
			ActionButton_HideOverlayGlow(self)
		end		
	end
end

function MonkTimers.TimerEvents(self, event, ...)
    if event == "SPELL_UPDATE_COOLDOWN" and AvailableSpells[self.cdspell] then 
        local start, duration, enable = GetSpellCooldown(self.cdspell)
        if (not start and not duration) or (duration <= 1.5 and not InCombatLockdown()) then
            self.timer:Stop()					
        else
            if duration == 0 then
                self.timer:Stop()
            elseif duration > 2 and self.timer.timer<=0 then
                self.timer:Start(start+duration-floor(GetTime()),duration)
            end
            CooldownFrame_SetTimer(self.cooldown, start, duration, enable)
        end 
    end
end

TigerPalmEvent = function(self, event, unit)
    if event == "UNIT_AURA" then
        if unit == "player" then
            local _,_,_,count,_,duration, expiration = UnitBuff("player", TigerPalmBuff)
            if count and count > 0 then
                self.timer:Start(count)
                self.timer:StartBarTimer(expiration-GetTime(), duration)
            elseif self.timer.timer>0 then
                self.timer:Stop()
            end
        end
    else
		GlowEvent(self, event, unit)
	end
end


local Shuffle = SpellNames[SpellIDs.Shuffle]

BlackoutKickEvent = function(self, event, unit)
    if unit == "player" then
        local _,_,_,count,_,duration, expiration = UnitBuff("player", Shuffle)
        if duration and duration > 0 then
            self.timer:Start(expiration-GetTime(), duration)
        elseif self.timer.timer>0 then
            self.timer:Stop()
        end
    end
end


local BlackoutKickName = SpellNames[SpellIDs.BlackoutKick]

BlackoutKickWWEvent = function(self, event, unit)
	if event == "UNIT_AURA" then
		if unit == "target" then
			local _,_,_,_,_,duration,expiration = UnitDebuff("target", BlackoutKickName, nil, "PLAYER")
			
			if duration then
				self.timer:StartBarTimer(expiration-GetTime(), duration)
				self.timer:Start(expiration-GetTime(), duration)
			else
				self.timer:StopBarTimer()
				self.timer:Stop()
			end
		end
	else
		GlowEvent(self, event, unit)
	end
end


local ElusiveBrewStacks = SpellNames[SpellIDs.ElusiveBrewStacks]
local ElusiveBrewBuff = SpellNames[SpellIDs.ElusiveBrewBuff]
local StackTexture = SpellTextures[SpellIDs.ElusiveBrewStacks]
local BuffTexture = SpellTextures[SpellIDs.ElusiveBrewBuff]

ElusiveBrewEvent = function(self, event, unit)
    if unit == "player" then
        local _,_,_,count,_,duration,expiration = UnitBuff("player", ElusiveBrewStacks)
        local _,_,_,_,_,buffduration,buffexpiration = UnitBuff("player", ElusiveBrewBuff)
        if buffduration and buffduration < 30 then
            self.timer.prohibitCooldown = false
            self.icon:SetTexture(BuffTexture)
            self.timer:StopBarTimer()
            self.timer.barTimerOnly = false
            self.timer:Start(buffexpiration-GetTime(), buffduration)            
        elseif count and count > 0 then
            self.timer.prohibitCooldown = true
            self.timer.barTimerOnly = true
            self.icon:SetTexture(StackTexture)
            self.timer:StartBarTimer(expiration-GetTime(), duration)
            self.timer:Start(count)
        else
            if self.timer.timer > 0 then
                self.timer:Stop()
            end
            if self.timer.barTimer > 0 then
                self.timer:StopBarTimer()
            end
        end 
    end
end

local Guard = SpellNames[SpellIDs.Guard]
local GuardActive = false

GuardEvent = function(self, event, unit)
	if event == "UNIT_AURA" then
		if unit == "player" then
			local _,_,_,count,_,duration,expiration = UnitBuff("player", Guard)
			if duration then
				self.timer:Start(expiration-GetTime(), duration)
				self.timer:StartBarTimer(expiration-GetTime(), duration)
			elseif self.timer.timer > 0 then
				self.timer:StopBarTimer()
				local cdstart, cdduration, cdenable = GetSpellCooldown(self.cdspell)
				if not cdduration then
					self.timer:Stop()
				end
			end
		end
	else
		GlowEvent(self, event, unit)
	end
end


CDAndBuffEvent = function(self, event, ...)
    if event == "SPELL_UPDATE_COOLDOWN" and AvailableSpells[self.cdspell] and not self.BuffIsRunning then 
        local start, duration, enable = GetSpellCooldown(self.cdspell)
        if (not start and not duration) or (duration <= 1.5 and not InCombatLockdown()) then
            self.timer:Stop()					
        else
            if duration == 0 then
                self.timer:Stop()
            elseif duration > 2 and self.timer.timer<=0 then
                self.timer:Start(start+duration-floor(GetTime()),duration)
            end
            CooldownFrame_SetTimer(self.cooldown, start, duration, enable)
        end 
    elseif event == "UNIT_AURA" then
        local unit = ...
        if unit == "player" then
            local timer = self.timer
            local _,_,_,count,_,duration,expiration = UnitBuff("player", self.cdspellName)
            if duration then
                timer:Start(expiration-GetTime(), duration)
                timer:StartBarTimer(expiration-GetTime(), duration)
                self.BuffIsRunning = true
                timer.reverseAlpha = false
            elseif self.BuffIsRunning then
                self.BuffIsRunning = false
                timer.reverseAlpha = true
                timer:StopBarTimer()
                local cdstart, cdduration, cdenable = GetSpellCooldown(self.cdspell)
                if cdduration then
                    timer:Start(cdstart+cdduration-floor(GetTime()),cdduration)
                else
                    timer:Stop()
                end
            end
        end        
    end
end


local DampenHarm = SpellNames[SpellIDs.DampenHarm]
local DampenHarmActive = false

DampenHarmEvent = function(self, event, unit)
    if event == "UNIT_AURA" then
        if unit == "player" then
            local timer = self.timer
            local _,_,_,count,_,duration, expiration = UnitBuff("player", DampenHarm)
            if count and count > 0 then
                timer.barTimerOnly = true
                timer.prohibitCooldown = true
                timer.reverseAlpha = false
                timer:StartBarTimer(expiration-GetTime(), duration)
                timer:Start(count,3)
                DampenHarmActive = true
            elseif DampenHarmActive then
                DampenHarmActive = false
                timer.barTimerOnly = false
                timer.prohibitCooldown = false
                timer.reverseAlpha = true
                timer:StopBarTimer()                
                local cdstart, cdduration, cdenable = GetSpellCooldown(self.cdspell)
                if cdduration and cdduration > 0 then
                    timer:Start( cdstart+cdduration-floor(GetTime()),cdduration)
                else
                    timer:Stop()
                end
            end
        end
    else
        MonkTimers.TimerEvents(self,event,unit)
    end
end


local TigereyeBrew = SpellNames[SpellIDs.TigereyeBrew]
local TigereyeStackTexture = SpellTextures[SpellIDs.TigereyeBrewStacks]
local TigereyeBuffTexture = SpellTextures[SpellIDs.TigereyeBrew]

TigereyeBrewEvent = function(self, event, unit)
    if unit == "player" then
        local _,_,_,count,_,duration,expiration = UnitBuff("player", TigereyeBrew)
        if duration and duration <= 15 then
            self.timer.prohibitCooldown = false
            self.icon:SetTexture(TigereyeBuffTexture)
            self.timer:StopBarTimer()
            self.timer.barTimerOnly = false
            self.timer:Start(expiration-GetTime(), duration)            
        elseif count and count > 0 then
            self.timer.prohibitCooldown = true
            self.timer.barTimerOnly = true
            self.icon:SetTexture(TigereyeStackTexture)
            self.timer:StartBarTimer(expiration-GetTime(), duration)
            self.timer:Start(count)
        else
            if self.timer.timer > 0 then
                self.timer:Stop()
            end
            if self.timer.barTimer > 0 then
                self.timer:StopBarTimer()
            end
        end 
    end
end


local SerpentsZeal = SpellNames[SpellIDs.SerpentsZeal]

SerpentsZealEvent = function(self, event, unit)
    if event == "UNIT_AURA" then
        if unit == "player" then
            local _,_,_,count,_,duration, expiration = UnitBuff("player", SerpentsZeal)
            if count and count > 0 then
                self.timer:Start(count)
                self.timer:StartBarTimer(expiration-GetTime(), duration)
            elseif self.timer.timer>0 then
                self.timer:Stop()
            end
        end
    end
end

local staggerLight = SpellNames[SpellIDs.StaggerLight]
local staggerModerate = SpellNames[SpellIDs.StaggerModerate]
local staggerHeavy = SpellNames[SpellIDs.StaggerHeavy]
local lightTexture = SpellTextures[SpellIDs.StaggerLight]
local moderateTexture = SpellTextures[SpellIDs.StaggerModerate]
local heavyTexture = SpellTextures[SpellIDs.StaggerHeavy]

local format = string.format

local function SetStaggerText(value)
	local maxHealth = UnitHealthMax("player")
	local percent = value/maxHealth*100
	if value > 1000000 then
		stagger.text:SetText(format("%.2fm", value/1000000) .. " ("..format("%.1f", percent).."%)")
	elseif value > 1000 then
		stagger.text:SetText(format("%.2fk", value/1000) .. " ("..format("%.1f", percent).."%)")
	else
		stagger.text:SetText(value .. " ("..format("%.1f", percent).."%)")
	end	
end


StaggerEvent = function(self, event)
	if event == "UNIT_AURA" then
		local _,_,_,_,_,_,_,_,_,_,_,_,_, amount = UnitDebuff("player", staggerLight)
		if amount then
			if amount > MonkTimers.ActiveProfile.StaggerMax then
				stagger:SetMinMaxValues(0,amount)
				stagger.background:SetMinMaxValues(0,amount)
				stagger.background:SetValue(amount)
				MonkTimers.ActiveProfile.StaggerMax = amount
			end
			stagger.icon:SetTexture(lightTexture)
			stagger:SetValue(amount)
			SetStaggerText(amount)
			stagger:SetStatusBarColor(0,1,0)
			stagger.background:SetStatusBarColor(0,1,0,0.3)

			return
		end
		local _,_,_,_,_,_,_,_,_,_,_,_,_, amount = UnitDebuff("player", staggerModerate)
		if amount then
			if amount > MonkTimers.ActiveProfile.StaggerMax then
				stagger:SetMinMaxValues(0,amount)
				stagger.background:SetMinMaxValues(0,amount)
				stagger.background:SetValue(amount)
				MonkTimers.ActiveProfile.StaggerMax = amount
			end
			stagger.icon:SetTexture(moderateTexture)
			stagger:SetValue(amount)
			SetStaggerText(amount)
			stagger:SetStatusBarColor(1,1,0)
			stagger.background:SetStatusBarColor(1,1,0,0.3)
			return
		end
		local _,_,_,_,_,_,_,_,_,_,_,_,_, amount = UnitDebuff("player", staggerModerate)
		if amount then
			if amount > MonkTimers.ActiveProfile.StaggerMax then
				stagger:SetMinMaxValues(0,amount)
				stagger.background:SetMinMaxValues(0,amount)
				stagger.background:SetValue(amount)
				MonkTimers.ActiveProfile.StaggerMax = amount
			end
			stagger.icon:SetTexture(heavyTexture)
			stagger:SetValue(amount)
			SetStaggerText(amount)
			stagger:SetStatusBarColor(1,0,0)
			stagger.background:SetStatusBarColor(1,0,0,0.3)
		else
			stagger:SetValue(0)
			stagger.text:SetText("")
			stagger.icon:SetTexture(lightTexture)
		end
	elseif event == "PLAYER_REGEN_ENABLED" then
       --[[ if MonkTimers.ActiveProfile.HideTimersOOC then
            self:Hide()
        end]]
        self:SetAlpha(MonkTimers.ActiveProfile.TimerOOCAlpha)
    elseif event == "PLAYER_REGEN_DISABLED" then
       --[[ if not self:IsVisible() then
            self:Show()
        end]]
		self:SetAlpha(1)
    end
end



ChiBarEvent = function(self, event, unit, power)
	if event == "UNIT_POWER" then
		if power == "LIGHT_FORCE" or power == "DARK_FORCE" then
			local light = UnitPower("player", SPELL_POWER_LIGHT_FORCE)
			for i = 1, self.maxLight do
				MonkHarmonyBar_SetEnergy(self["lightEnergy"..i], i<=light);
			end
		end
	elseif event == "UNIT_MAXPOWER" then
		local maxLight = UnitPowerMax("player", SPELL_POWER_LIGHT_FORCE)
		if self.maxLight ~= maxLight then
			if maxLight == 4 then
				self.lightEnergy1:SetPoint("LEFT", -43, 1)
				self.lightEnergy2:SetPoint("LEFT", self.lightEnergy1, "RIGHT", 5, 0)
				self.lightEnergy3:SetPoint("LEFT", self.lightEnergy2, "RIGHT", 5, 0)
				self.lightEnergy4:SetPoint("LEFT", self.lightEnergy3, "RIGHT", 5, 0)
				self.lightEnergy5:Hide()
			else
				self.lightEnergy1:SetPoint("LEFT", -46, 1)
				self.lightEnergy2:SetPoint("LEFT", self.lightEnergy1, "RIGHT", 1, 0)
				self.lightEnergy3:SetPoint("LEFT", self.lightEnergy2, "RIGHT", 1, 0)
				self.lightEnergy4:SetPoint("LEFT", self.lightEnergy3, "RIGHT", 1, 0)
				self.lightEnergy5:Show();
			end
			self.maxLight = maxLight;
		end
	elseif event == "PLAYER_REGEN_ENABLED" then
        if MonkTimers.ActiveProfile.HideTimersOOC then
            self:Hide()
        end
        self:SetAlpha(MonkTimers.ActiveProfile.TimerOOCAlpha)
    elseif event == "PLAYER_REGEN_DISABLED" then
        if not self:IsVisible() then
            self:Show()
        end
		self:SetAlpha(1)
	elseif event == "PET_BATTLE_OPENING_START" then
		self:Hide()
	elseif event == "PET_BATTLE_CLOSE" then
		if self.active and not MonkTimers.ActiveProfile.HideTimersOOC then
			self:Show()
		end
    end
end


ChiBarUpdate = function(self)
	local power = UnitPower("player", self.powerType)
	self.energyBar:SetValue(power)
	if power > 1000 then
		power = format("%.1fk", power/1000)
	end
	self.energyBar.text:SetText(power)
end

local introIcon = CreateFrame("FRAME", "MonkTimers_TimerIntro", UIParent, "IconIntroTemplate")

function MonkTimers.TimerIntroAnimation(spell)
	local doAnimation = false
	for i=1,#cds do
		if cds[i].button.cdspell == spell then doAnimation = i end
	end
	if not doAnimation then return end
	introIcon:ClearAllPoints()
	introIcon:SetPoint("CENTER", cds[doAnimation].button, 0,0)
	introIcon.icon.icon:SetTexture(SpellTextures[spell])
	introIcon.icon.slot = 0
	introIcon.icon.flyin:Play(1)
end
